from flask import request, jsonify, g
from flask_jwt_extended import jwt_required
import datetime
from bson import ObjectId

from app.api.v1 import api_bp
from app import mongo
from app.utils.auth import permission_required
from app.schemas.invoice import InvoiceSchema, InvoiceGenerateSchema
from app.utils.common import normalize_data, paginate, generate_id

@api_bp.route('/invoices', methods=['GET'])
@jwt_required()
@permission_required('invoice:read')
def get_invoices():
    """获取发票列表"""
    # 获取查询参数
    page = request.args.get('page', 1, type=int)
    limit = request.args.get('limit', 20, type=int)
    sort_by = request.args.get('sortBy', 'createdAt')
    order = request.args.get('order', 'desc')
    
    # 构建查询条件
    query = {}
    
    # 按患者ID筛选
    patient_id = request.args.get('patientId')
    if patient_id:
        query['patientId'] = patient_id
    
    # 按支付ID筛选
    payment_id = request.args.get('paymentId')
    if payment_id:
        query['paymentId'] = payment_id
    
    # 按账单ID筛选
    billing_id = request.args.get('billingId')
    if billing_id:
        query['billingId'] = billing_id
    
    # 按状态筛选
    status = request.args.get('status')
    if status and status != 'all':
        query['status'] = status
    
    # 按日期范围筛选
    start_date = request.args.get('startDate')
    if start_date:
        try:
            start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')
            query['invoiceDate'] = {'$gte': start_date}
        except ValueError:
            pass
    
    end_date = request.args.get('endDate')
    if end_date:
        try:
            end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')
            end_date = end_date.replace(hour=23, minute=59, second=59)
            if 'invoiceDate' in query:
                query['invoiceDate']['$lte'] = end_date
            else:
                query['invoiceDate'] = {'$lte': end_date}
        except ValueError:
            pass
    
    # 确定排序
    sort_direction = -1 if order.lower() == 'desc' else 1
    
    # 获取数据
    invoices_cursor = mongo.db.invoices.find(query).sort(sort_by, sort_direction)
    
    # 分页
    paginated_data = paginate(invoices_cursor, page, limit)
    
    # 标准化数据
    invoices = []
    for invoice in paginated_data['items']:
        # 标准化发票数据
        normalized_invoice = normalize_data(invoice)
        invoices.append(normalized_invoice)
    
    return jsonify({
        'success': True,
        'data': {
            'total': paginated_data['total'],
            'page': paginated_data['page'],
            'limit': paginated_data['per_page'],
            'invoices': invoices
        }
    }), 200

@api_bp.route('/invoices/<id>', methods=['GET'])
@jwt_required()
@permission_required('invoice:read')
def get_invoice(id):
    """获取发票详情"""
    # 查询发票
    invoice = None
    if ObjectId.is_valid(id):
        invoice = mongo.db.invoices.find_one({'_id': ObjectId(id)})
    
    if not invoice:
        invoice = mongo.db.invoices.find_one({'invoiceId': id})
    
    if not invoice:
        return jsonify({
            'success': False,
            'message': '发票不存在'
        }), 404
    
    # 获取关联的支付信息
    payment_info = None
    if 'paymentId' in invoice:
        payment_id = invoice['paymentId']
        if ObjectId.is_valid(payment_id):
            payment = mongo.db.payments.find_one({'_id': ObjectId(payment_id)})
        else:
            payment = mongo.db.payments.find_one({'paymentId': payment_id})
        
        if payment:
            payment_info = {
                'id': str(payment['_id']),
                'paymentId': payment.get('paymentId', ''),
                'amount': payment.get('amount', 0),
                'paymentMethod': payment.get('paymentMethod', ''),
                'status': payment.get('status', ''),
                'paidAt': payment.get('paidAt', '')
            }
    
    # 获取账单信息
    billing_info = None
    if 'billingId' in invoice:
        billing_id = invoice['billingId']
        if ObjectId.is_valid(billing_id):
            billing = mongo.db.billings.find_one({'_id': ObjectId(billing_id)})
        else:
            billing = mongo.db.billings.find_one({'billingId': billing_id})
        
        if billing:
            billing_info = {
                'id': str(billing['_id']),
                'billingId': billing.get('billingId', ''),
                'totalAmount': billing.get('totalAmount', 0),
                'status': billing.get('status', '')
            }
    
    # 标准化数据
    normalized_invoice = normalize_data(invoice)
    
    return jsonify({
        'success': True,
        'data': {
            'invoice': normalized_invoice,
            'paymentInfo': payment_info,
            'billingInfo': billing_info
        }
    }), 200

@api_bp.route('/invoices/generate', methods=['POST'])
@jwt_required()
@permission_required('invoice:create')
def generate_invoice():
    """生成发票"""
    # 验证请求数据
    schema = InvoiceGenerateSchema()
    errors = schema.validate(request.json)
    if errors:
        return jsonify({
            'success': False,
            'message': '请求数据验证失败',
            'errors': errors
        }), 400
    
    data = request.json
    
    # 查询支付记录
    payment_id = data.get('paymentId')
    payment = None
    
    if ObjectId.is_valid(payment_id):
        payment = mongo.db.payments.find_one({'_id': ObjectId(payment_id)})
    
    if not payment:
        payment = mongo.db.payments.find_one({'paymentId': payment_id})
    
    if not payment:
        return jsonify({
            'success': False,
            'message': '支付记录不存在'
        }), 404
    
    # 验证支付状态
    if payment.get('status') != '成功':
        return jsonify({
            'success': False,
            'message': f'支付状态为{payment.get("status")}，只能为已成功支付的记录生成发票'
        }), 400
    
    # 检查是否已经有发票
    existing_invoice = mongo.db.invoices.find_one({'paymentId': str(payment['_id'])})
    if existing_invoice:
        return jsonify({
            'success': False,
            'message': '该支付记录已生成发票'
        }), 400
    
    # 查询账单
    billing = None
    if 'billingId' in payment:
        billing_id = payment['billingId']
        if ObjectId.is_valid(billing_id):
            billing = mongo.db.billings.find_one({'_id': ObjectId(billing_id)})
        else:
            billing = mongo.db.billings.find_one({'billingId': billing_id})
    
    if not billing:
        return jsonify({
            'success': False,
            'message': '关联的账单不存在'
        }), 400
    
    # 查询患者
    patient = None
    if 'patientId' in payment:
        patient_id = payment['patientId']
        if isinstance(patient_id, str) and ObjectId.is_valid(patient_id):
            patient_id = ObjectId(patient_id)
        patient = mongo.db.patients.find_one({'_id': patient_id})
    
    if not patient:
        return jsonify({
            'success': False,
            'message': '患者信息不存在'
        }), 400
    
    # 创建发票项目
    invoice_items = []
    if 'items' in billing:
        for item in billing['items']:
            invoice_items.append({
                'description': item.get('description', ''),
                'quantity': 1,
                'unitPrice': item.get('amount', 0),
                'amount': item.get('amount', 0)
            })
    
    # 创建发票数据
    invoice_data = {
        'invoiceId': generate_id('I'),
        'invoiceNumber': generate_invoice_number(),
        'paymentId': str(payment['_id']),
        'billingId': str(billing['_id']),
        'patientId': str(patient['_id']),
        'patientName': patient.get('name', ''),
        'items': invoice_items,
        'totalAmount': payment.get('amount', 0),
        'paidAmount': payment.get('amount', 0),
        'invoiceDate': datetime.datetime.utcnow(),
        'status': '已开具',
        'createdAt': datetime.datetime.utcnow(),
        'updatedAt': datetime.datetime.utcnow()
    }
    
    # 如果有医保信息，添加到发票
    if 'insuranceInfo' in billing and billing['insuranceInfo'].get('isInsurance'):
        invoice_data['insurancePaid'] = billing['insuranceInfo'].get('insurancePay', 0)
    
    # 保存到数据库
    result = mongo.db.invoices.insert_one(invoice_data)
    
    # 生成发票下载URL
    invoice_url = f"/api/v1/invoices/{str(result.inserted_id)}/download"
    
    # 更新发票URL
    mongo.db.invoices.update_one(
        {'_id': result.inserted_id},
        {'$set': {'invoiceUrl': invoice_url}}
    )
    
    return jsonify({
        'success': True,
        'message': '发票生成成功',
        'data': {
            'id': str(result.inserted_id),
            'invoiceId': invoice_data['invoiceId'],
            'invoiceNumber': invoice_data['invoiceNumber'],
            'totalAmount': invoice_data['totalAmount'],
            'status': invoice_data['status'],
            'invoiceUrl': invoice_url,
            'createdAt': invoice_data['createdAt'].isoformat()
        }
    }), 201

@api_bp.route('/invoices/<id>/void', methods=['PUT'])
@jwt_required()
@permission_required('invoice:update')
def void_invoice(id):
    """作废发票"""
    # 查询发票
    invoice = None
    if ObjectId.is_valid(id):
        invoice = mongo.db.invoices.find_one({'_id': ObjectId(id)})
    
    if not invoice:
        invoice = mongo.db.invoices.find_one({'invoiceId': id})
    
    if not invoice:
        return jsonify({
            'success': False,
            'message': '发票不存在'
        }), 404
    
    # 验证发票状态
    if invoice.get('status') == '已作废':
        return jsonify({
            'success': False,
            'message': '发票已作废'
        }), 400
    
    # 更新发票状态
    update_data = {
        'status': '已作废',
        'updatedAt': datetime.datetime.utcnow()
    }
    
    # 更新数据库
    mongo.db.invoices.update_one({'_id': invoice['_id']}, {'$set': update_data})
    
    return jsonify({
        'success': True,
        'message': '发票已作废',
        'data': {
            'id': str(invoice['_id']),
            'invoiceId': invoice.get('invoiceId', ''),
            'status': '已作废'
        }
    }), 200

@api_bp.route('/invoices/<id>/download', methods=['GET'])
@jwt_required()
@permission_required('invoice:read')
def download_invoice(id):
    """下载发票"""
    # 查询发票
    invoice = None
    if ObjectId.is_valid(id):
        invoice = mongo.db.invoices.find_one({'_id': ObjectId(id)})
    
    if not invoice:
        invoice = mongo.db.invoices.find_one({'invoiceId': id})
    
    if not invoice:
        return jsonify({
            'success': False,
            'message': '发票不存在'
        }), 404
    
    # 这里简化处理，实际应该生成PDF并提供下载
    # 在真实场景中，您可能需要集成PDF生成库
    
    # 标准化数据
    normalized_invoice = normalize_data(invoice)
    
    # 临时返回发票数据，实际应该返回文件
    return jsonify({
        'success': True,
        'message': '获取发票成功',
        'data': {
            'invoice': normalized_invoice,
            'download_info': '在真实实现中，这里应该返回发票PDF文件'
        }
    }), 200

def generate_invoice_number():
    """生成发票号码"""
    # 生成格式：INV + 年月日 + 4位序号
    today = datetime.datetime.now().strftime('%Y%m%d')
    
    # 查找今天最后一个发票号
    last_invoice = mongo.db.invoices.find_one(
        {'invoiceNumber': {'$regex': f'^INV{today}'}},
        sort=[('invoiceNumber', -1)]
    )
    
    if last_invoice and 'invoiceNumber' in last_invoice:
        try:
            last_number = int(last_invoice['invoiceNumber'][11:])
            new_number = last_number + 1
        except ValueError:
            new_number = 1
    else:
        new_number = 1
    
    # 格式化为4位数
    return f"INV{today}{new_number:04d}" 